package com.xebia.lightning.scheduler;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.xebia.lightning.domain.Job;
import com.xebia.lightning.domain.Tweet;
import com.xebia.lightning.service.JobService;
import com.xebia.lightning.service.TweetService;

//@Component
public class JobInfoRetriever {

    private Logger logger = Logger.getLogger(JobInfoRetriever.class);

    @Autowired
    private TweetService tweetService;

    @Autowired
    private JobService jobService;

    long count = 0;

    @Scheduled(fixedRate = 300000l)
    public void parseTweetsToJob() throws Exception {
        count++;
        logger.info("Running Jobs Scheduler .... " + count);

        List<Tweet> allUnprocessedTweets = tweetService
                .findAllUnprocessedTweets();
        logger.info("Total number of unprocessed tweets : "
                + allUnprocessedTweets.size());
        for (Tweet tweet : allUnprocessedTweets) {

            try {
                long tweetId = tweet.getTweetId();

                if (!CollectionUtils.isEmpty(jobService.findAllByTweetId(tweetId))) {
                    logger.warn("There is already a job existing for tweetId : "
                            + tweetId);
                    continue;
                }
                String tweetText = tweet.getText();
                logger.trace("Tweet Text : " + tweetText);
                Job job = parseATweetToJob(tweetText);
                if (job == null) {
                    tweet.setProcessed(true);
                    tweetService.updateTweet(tweet);
                    continue;
                }
                job.setTweetId(tweet.getTweetId());
                job.setPostedDate(tweet.getCreationDate());
                logger.debug("Persiting Job : " + job);
                jobService.saveJob(job);
                logger.info("Persited Job : " + job);
            } catch (Exception e) {
                logger.warn("Exception encountered while processing tweet : " + tweet, e);
            } finally {
                tweet.setProcessed(true);
                tweetService.updateTweet(tweet);

            }
        }

    }

    public static void main(String[] args) {
        JobInfoRetriever jobInfoRetriever = new JobInfoRetriever();
        Job job = jobInfoRetriever
                .parseATweetToJob("HP Magician - We need a web developer bitten by the entrepreneurial bug! at http://t.co/nL6TfKkk (India... http://t.co/msF8g6yy #tech #jobs");
        System.out.println(job);
    }

    private Job parseATweetToJob(String tweetText) {
        List<String> links = pullLinks(tweetText);
        if (CollectionUtils.isEmpty(links)) {
            logger.info("No Links Found");
            return null;
        }
        List<String> skills = findSkills(tweetText);
        if (CollectionUtils.isEmpty(skills)) {
            logger.info("No Skills Found");
            return null;
        }

        String jobCountry = jobCountry(tweetText);
        List<String> jobLocations = jobLocation(tweetText);

        if (StringUtils.isBlank(jobCountry)
                && CollectionUtils.isEmpty(jobLocations)) {
            logger.info("No JobLocation Found");
            return null;
        }

        Job job = new Job();
        String url = links.get(0);
        job.setJobUrl(url);
        job.setLocation(listAsString(jobLocations));

        job.setSkills(listAsString(skills));
        job.setCountryName(jobCountry);
        Document doc = null;
        try {
            doc = Jsoup.connect(url).get();
        } catch (Exception e) {
            logger.warn("exception encountered while processing url " + url, e);
            return null;
        }
        String title = doc.title();
        job.setJobTitle(title);
        return job;
    }

    private String listAsString(List<String> list) {
        StringBuilder sb = new StringBuilder();
        for (String str : list) {
            sb.append(str).append(",");
        }
        String str = sb.toString();
        if (StringUtils.isNotBlank(str)) {
            int lastIndexOf = StringUtils.lastIndexOf(str, ",");
            str = str.substring(0, lastIndexOf);
        }
        return str;
    }

    private String jobCountry(String tweetText) {
        String location = "india";
        tweetText = tweetText.replaceAll("\\p{P}+", " ");
        String[] words = tweetText.split("\\W+");
        double locationLength = location.length();
        boolean locationFound = false;
        for (String word : words) {
            if ((StringUtils.getLevenshteinDistance(location, word) / locationLength) > .9d) {
                locationFound = true;
            }
        }
        return locationFound ? location : null;
    }

    private List<String> jobLocation(String tweetText) {
        String[] locations = { "bangalore", "gurgaon", "delhi", "mumbai",
                "jaipur", "chandigarh", "noida", "kolkata", "chennai",
                "hyderabad", "pune", "lucknow", "ghaziabad", "Bengaluru" };
        List<String> jobLocations = new ArrayList<String>();

        for (String location : locations) {
            if (org.apache.commons.lang.StringUtils.containsIgnoreCase(
                    tweetText, location)) {
                jobLocations.add(location);
            }
        }
        return jobLocations;
    }

    private List<String> findSkills(String tweetText) {
        String[] skills = { "joomla", "java", "ruby", "python", "scala",
                "unix", "developer", "php", "lamp", "c#", "rails", "python",
                "oracle", ".net", "Storage Development Engineer",
                "web developer", "hadoop", "dotnet", "Android", "iphone", "Cloud Developer" };

        List<String> foundSkills = new ArrayList<String>();

        for (String location : skills) {
            if (org.apache.commons.lang.StringUtils.containsIgnoreCase(
                    tweetText, location)) {
                foundSkills.add(location);
            }
        }
        return foundSkills;
    }

    // Pull all links from the body for easy retrieval
    private static List<String> pullLinks(String text) {
        List<String> links = new ArrayList<String>();

        String regex = "\\(?\\b(http://|www[.])[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);
        while (m.find()) {
            String urlStr = m.group();
            if (urlStr.startsWith("(") && urlStr.endsWith(")")) {
                urlStr = urlStr.substring(1, urlStr.length() - 1);
            }
            links.add(urlStr);
        }
        return links;
    }

}
